package com.herench.bs.support;

import com.herench.bs.annotation.Handler;
import com.herench.bs.rtconfig.CleverContextConfig;
import com.herench.bs.rtconfig.ClinicRulesConfig;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by ThinkPad on 2017/8/24.
 */

@Component
public class CleverClinicContext {

    private static final Logger logger = Logger.getLogger(CleverClinicContext.class);


    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private Environment environment;

    private Set<String> greenChannelCodes;

    private CleverContextConfig contextConfig;

    private ClinicRulesConfig clinicRulesConfig;

    private boolean alive;

    private ServicePool<String, MessageHandler> messageHandlerServicePool;


    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    private String basePackage = "com.herench.bs.handler";
    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
    private String resourcePattern = DEFAULT_RESOURCE_PATTERN;
    private MetadataReaderFactory metadataReaderFactory;




    public boolean isAlive() {
        return alive;
    }

    public CleverClinicContext() {
    }

    public CleverContextConfig getContextConfig() {
        return contextConfig;
    }

    public void setContextConfig(CleverContextConfig contextConfig) {
        this.contextConfig = contextConfig;
    }


    @PostConstruct
    public synchronized void init() throws Exception {
        if (logger.isInfoEnabled()) {
            logger.debug("init message processor......");
        }
        /**
         * 初始化handler容器池
         */
        messageHandlerServicePool = new SimpleMessageHandlerServicePool();
        /**
         * 构建元信息阅读器工厂
         */
        this.metadataReaderFactory = new CachingMetadataReaderFactory();

        /**
         * 解析需要被扫描的包路径
         */
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern;
        /**
         * 获取被扫描的包路径下的所有*.class资源
         */
        Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
        /**
         * 如果资源存在的话开始迭代
         */
        if(resources!=null && resources.length>0){
            /**
             * 循环迭代解析资源
             */
            for (Resource resource : resources) {
                /**
                 * 如果资源可读，则进行后续解析
                 */
                if (resource.isReadable()) {
                    /**
                     * 获取资源的元信息
                     */
                    MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                    /**
                     * 获取资源的注解元信息
                     */
                    AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
                    /**
                     * 如果存在@Handler注解，则进行后续操作
                     */
                    if (annotationMetadata.hasAnnotation(Handler.class.getName())) {
                        /**
                         * 获取类名
                         */
                        String className = metadataReader.getClassMetadata().getClassName();
                        /**
                         * 获取原始类
                         */
                        Class<MessageHandler> handlerClass = (Class<MessageHandler>) Class.forName(className);
                        /**
                         * 获取handler对象实例
                         */
                        MessageHandler handler = getApplicationContext().getBean(handlerClass);
                        /**
                         * 获取handler对象的@handler注解对象信息
                         */
                        Handler annotation = handlerClass.getDeclaredAnnotation(Handler.class);
                        /**
                         * 将handler根据@Handler注解信息放入handler池
                         */
                        handler.setFunctionCode(annotation.code());
                        handler.setFunctionName(annotation.name());
                        this.messageHandlerServicePool.release(annotation.code(), handler);
                    }
                }
            }
        }

        /**
         * 配置绿色通道
         */
        greenChannelCodes = new HashSet<>();
        greenChannelCodes.add("100102");
        greenChannelCodes.add("100109");
        greenChannelCodes.add("100202");
        greenChannelCodes.add("100301");
        greenChannelCodes.add("100302");
        greenChannelCodes.add("100235");
        CleverContextConfig contextConfig = new CleverContextConfig();
        this.contextConfig = contextConfig;
        this.clinicRulesConfig = new ClinicRulesConfig(environment.getProperty("clinic_date_days"));
        alive = true;
    }


    public ServicePool<String, MessageHandler> getMessageHandlerServicePool() {
        return messageHandlerServicePool;
    }


    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public Set<String> getGreenChannelCodes() {
        return greenChannelCodes;
    }

    /**
     * 目前写死返回胸科代码
     *
     * @param channelCode
     * @return
     */
    public String getHospitalCodeByChannelCode(String channelCode) {
        return "0001";
    }


    private String resolveBasePackage(String basePackage) {
        return ClassUtils.convertClassNameToResourcePath(basePackage);
    }
}
